package com.yeyks.config;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 * Author bugui.lw
 * 2017-03-04 20:55
 */
@Slf4j
@Configuration(value = "commonConfigure4HttpClient")
@ConditionalOnMissingBean(OkHttpClient.class)
public class Configure4HttpClient {

    private ConcurrentMap<String, List<Cookie>> cookieStore = Maps.newConcurrentMap();

    @Bean
    public OkHttpClient okHttpClient() {
        OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient().newBuilder().cookieJar(new CookieJar() {
            @Override
            public void saveFromResponse(HttpUrl httpUrl, List<Cookie> newCookies) {
                if (newCookies == null) return;
                String host = httpUrl.host();
                List<Cookie> oldCookies = getDomainCookie(host);
                if (oldCookies == null) {
                    storeDomainCookie(host, newCookies);
                    return;
                }

//                新老cookie都存在的时候，重新计算一遍，以新的为准，老的做补全
                List<Cookie> finalCookies = Lists.newArrayList(newCookies);
                Map<String, Cookie> newCookieMap = Maps.newHashMap();
                for (Cookie newCookie : newCookies) {
                    newCookieMap.put(newCookie.name(), newCookie);
                }

                for (Cookie oldCookie : oldCookies) {
                    if (!newCookieMap.containsKey(oldCookie.name())) {
                        finalCookies.add(oldCookie);
                    } else {
                        Cookie newCookie = newCookieMap.get(oldCookie.name());
                        if (!newCookie.name().equals(oldCookie.name())
                                || !newCookie.value().equals(oldCookie.value())) {
                            log.error("cookie updated, newCookie = {}, oldCookie = {}", new Object[]{newCookie, oldCookie});
                        }
                    }
                }

                storeDomainCookie(host, finalCookies);
            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                List<Cookie> cookies = getDomainCookie(httpUrl.host());
                if (cookies == null) {
                    return Collections.EMPTY_LIST;
                }
                return cookies;
            }
        });

//        设置ua
        okHttpClientBuilder.addInterceptor(chain -> {
            Request originalRequest = chain.request();
            Request requestWithUserAgent = originalRequest.newBuilder()
                    .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .header("Accept-Language:", "zh-cn")
                    .header("Accept", "*/*")
                    .build();
            if (originalRequest.url().url().getHost().contains("alimama")) {
                requestWithUserAgent = requestWithUserAgent.newBuilder()
                        .header("Referer", "http://media.alimama.com/account/overview.htm")
                        .build();
            }
            if (originalRequest.url().url().getHost().contains("dataoke")) {
                requestWithUserAgent = requestWithUserAgent.newBuilder()
                        .header("Referer", "http://www.dataoke.com/top_sell")
                        .build();
            }
            return chain.proceed(requestWithUserAgent);
        });
        return okHttpClientBuilder.build();
    }

    private void storeDomainCookie(String domain, List<Cookie> cookies) {
        cookieStore.put(rootHost(domain), cookies);
    }

    private List<Cookie> getDomainCookie(String domain) {
        return cookieStore.get(rootHost(domain));
    }

    private String rootHost(String host) {
        String[] hostSplit = host.split("\\.");
        String rootHost = host;
        if (hostSplit.length > 2) {
            rootHost = hostSplit[hostSplit.length - 2] + "." + hostSplit[hostSplit.length - 1];
        }
        return rootHost;
    }
}
